package com.ihr360.insurance.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.model.type.BenefitCategory;
import com.ihr360.insurance.dao.CompanyBenefitReposity;
import com.ihr360.insurance.entity.vo.CompanyBenefitSimpleVo;
import com.ihr360.insurance.model.dto.benefits.CompanyBenefit;
import com.ihr360.insurance.model.dto.benefits.CompanyBenefitConfig;
import com.ihr360.insurance.model.dto.benefits.MandatoryBenefitsMode;
import com.ihr360.insurance.model.vo.CompanyBenefitVo;
import com.ihr360.insurance.service.CompanyBenefitService;
import com.ihr360.insurance.service.StaffBenefitService;
import com.ihr360.rest.reposity.SimpleRestReposity;
import com.ihr360.rest.service.AbstractSimpleRestServiceImpl;
import com.ihr360.validation.ValidationUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author david.wei
 */
@Service
public class CompanyBenefitServiceImpl extends AbstractSimpleRestServiceImpl<CompanyBenefit, Long> implements CompanyBenefitService {
    @Autowired
    private CompanyBenefitReposity reposity;

    @Autowired
    private StaffBenefitService staffBenefitService;

    @Override
    public SimpleRestReposity<CompanyBenefit, Long> getSimpleRestReposity() {
        return reposity;
    }

    @Override
    public Map<Long, String> getCompanyBenefitModes(String companyId, BenefitCategory category) {
        Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
        if (CollectionUtils.isEmpty(idsMap)) {
            return Maps.newHashMap();
        }

        List<CompanyBenefit> companyBenefits = reposity.findAllByIdIn(idsMap.keySet());
        if (CollectionUtils.isEmpty(companyBenefits)) {
            return Maps.newHashMap();
        }
        Map<Long, String> result = new TreeMap<>();
        companyBenefits.stream()
                .filter(benefit -> benefit.getVoGroup() != null && benefit.getVoGroup().getCategory() == category)
                .forEach(benefit -> {
                    if (benefit.getGroup() != null && benefit.getGroup().getMode() != null) {
                        MandatoryBenefitsMode mode = benefit.getGroup().getMode();
                        result.put(mode.getId(), mode.getName());
                    }
                });
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveBenefit(String companyId, CompanyBenefit benefit) {
        String name = benefit.getName();
        ValidationUtils.rejectIfEmpty(name, "", "方案名称不能为空");
        ValidationUtils.rejectIfAnyNull("", "方案数据不能为空", benefit);
        //创建时，校验名称
        if (benefit.getId() == null) {
            Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
            if (CollectionUtils.isNotEmpty(idsMap)) {
                int nameCount = reposity.countByCompanyIdAndIdInAndName(companyId, idsMap.keySet(), name);
                ValidationUtils.rejectGt(nameCount, 0, "", "方案名称已存在，请修改");
            }
        } else {
            CompanyBenefit one = super.getOne(benefit.getId());
            ValidationUtils.rejectIfEmpty(one, "", "方案不存在，请刷新重试");
            //更新时，名称发生修改，校验重复性
            if (!name.equals(one.getName())) {
                Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
                if (CollectionUtils.isNotEmpty(idsMap)) {
                    int nameCount = reposity.countByCompanyIdAndIdInAndName(companyId, idsMap.keySet(), name);
                    ValidationUtils.rejectGt(nameCount, 0, "", "方案名称已存在，请修改");
                }
            }
            benefit.setStaffCount(one.getStaffCount());
        }
        benefit.setCompanyId(companyId);
        List<CompanyBenefitConfig> companyConfigs = benefit.getCompanyConfigs();
        if (CollectionUtils.isNotEmpty(companyConfigs)) {
            for (CompanyBenefitConfig config : companyConfigs) {
                config.setCompanyBenefit(benefit);
            }
        }
        CompanyBenefit save = reposity.save(benefit);
        return save.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBenefits(List<CompanyBenefit> benefits) {
        if (CollectionUtils.isNotEmpty(benefits)) {
            reposity.save(benefits);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean copyBenefit(String name, Long companyBenefitId) {
        CompanyBenefit source = super.getOne(companyBenefitId);
        ValidationUtils.rejectIfEmpty(source, null, "要复制的方案不存在，请刷新后重试");
        Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
        if (CollectionUtils.isNotEmpty(idsMap)) {
            int nameCount = reposity.countByCompanyIdAndIdInAndName(source.getCompanyId(), idsMap.keySet(), name);
            ValidationUtils.rejectGt(nameCount, 0, "", "指定的方案名称已存在，请修改");
        }

        CompanyBenefit copy = new CompanyBenefit();
        BeanUtils.copyProperties(source, copy, "id", "companyConfigs",
                "houseFunds", "socialInsurances", "socialInsuranceCount", "houseFundCount");
        copy.setName(name);
        copy.setId(null);
        List<CompanyBenefitConfig> companyConfigs = source.getCompanyConfigs();
        if (CollectionUtils.isNotEmpty(companyConfigs)) {
            companyConfigs.forEach(item -> {
                CompanyBenefitConfig newConfig = new CompanyBenefitConfig();
                BeanUtils.copyProperties(item, newConfig, "id", "companyBenefit");
                newConfig.setCompanyBenefit(copy);
                copy.getCompanyConfigs().add(newConfig);
            });
        }
        reposity.save(copy);
        return true;
    }

    @Override
    public List<CompanyBenefit> getCompanyBenefitsIn(List<Long> ids) {
        return reposity.findAllByIdIn(ids);
    }

    @Override
    public List<CompanyBenefitVo> getEnabledCompanyBenefits(String companyId) {
        Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
        if (CollectionUtils.isEmpty(idsMap)) {
            return Collections.emptyList();
        }

        List<CompanyBenefit> companyBenefits = reposity.findAllByIdIn(idsMap.keySet());
        companyBenefits.removeIf(benefit -> !benefit.isEnabled());
        if (CollectionUtils.isEmpty(companyBenefits)) {
            return Collections.emptyList();
        }
        return getCompanyBenefitVos(companyBenefits);
    }

    @Override
    public List<CompanyBenefitSimpleVo> getCompanyBenefitVos(String companyId) {
        Map<Long, Integer> idsMap = authUserResourceService.queryUserResourcesPrivilegeWithLongId(CompanyBenefit.class);
        if (CollectionUtils.isEmpty(idsMap)) {
            return Collections.emptyList();
        }

        List<CompanyBenefit> companyBenefits = reposity.findAllByIdIn(idsMap.keySet());
        if (CollectionUtils.isEmpty(companyBenefits)) {
            return Collections.emptyList();
        }
        List<CompanyBenefitSimpleVo> result = Lists.newArrayListWithCapacity(companyBenefits.size());
        companyBenefits.forEach(item -> result.add(new CompanyBenefitSimpleVo(item.getId(), item.getName(),
                item.getGroup() != null ? item.getGroup().getCategory() : null, item.getGroupDivisionId())));
        return result;
    }

    private List<CompanyBenefitVo> getCompanyBenefitVos(List<CompanyBenefit> benefits) {
        if (CollectionUtils.isEmpty(benefits)) {
            return Collections.emptyList();
        }
        List<CompanyBenefitVo> result = Lists.newArrayListWithCapacity(benefits.size());
        benefits.forEach(item -> {
            CompanyBenefitVo vo = new CompanyBenefitVo();
            vo.setId(item.getId());
            vo.setName(item.getName());
            vo.setGroup(item.getVoGroup());
//            vo.setHfTaxFreeRatio(item.getHfTaxFreeRatio());
            vo.setBenefitConfigs(item.getVoCompanyConfigs());
            result.add(vo);
        });
        return result;
    }
}
